﻿#region Includes
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using AltSerialize;
using System.IO;
using KellermanSoftware.CompareNetObjects;
#endregion
namespace AltSerializer.Tests
{
    [TestFixture(Description = "Tests for CompareObjects Port"), Category("CompareObjects")]
    public class AltSerializerTests
    {
        #region Class Variables
        private CompareObjects _compare = null;
        private AltSerialize.AltSerializer _serializer = null;
        private MemoryStream _memStream = null;
        #endregion

        #region Setup/Teardown

        /// <summary>
        /// Code that is run once for a suite of tests
        /// </summary>
        [TestFixtureSetUp]
        public void TestFixtureSetup()
        {

        }

        /// <summary>
        /// Code that is run once after a suite of tests has finished executing
        /// </summary>
        [TestFixtureTearDown]
        public void TestFixtureTearDown()
        {

        }

        /// <summary>
        /// Code that is run before each test
        /// </summary>
        [SetUp]
        public void Initialize()
        {
            _compare = new CompareObjects();
            _compare.MaxDifferences = 1000;
            _memStream = new MemoryStream();
            _serializer = new AltSerialize.AltSerializer(_memStream);
            _serializer.SerializeProperties = true;
        }

        /// <summary>
        /// Code that is run after each test
        /// </summary>
        [TearDown]
        public void Cleanup()
        {
        }
        #endregion

        #region Primitive Tests

        /// <summary>
        /// This is a test to make sure the compare is working
        /// </summary>
        [Test]
        public void PrimitiveFieldsClassCompareTest()
        {
            PrimitiveFields obj1 = new PrimitiveFields();
            obj1.Setup();
            PrimitiveFields obj2 = Common.CloneWithSerialization(obj1);

            if (!_compare.Compare(obj1, obj2))
                throw new Exception(_compare.DifferencesString);
        }

        /// <summary>
        /// Test serialization/deserialization of primitive types
        /// </summary>
        [Test]
        public void PrimitiveFieldsClassTest()
        {
            PrimitiveFields obj1 = new PrimitiveFields();
            obj1.Setup();

            _serializer.SerializeProperties = false;
            _serializer.Serialize(obj1, obj1.GetType());
            _memStream.Seek(0, SeekOrigin.Begin);
            PrimitiveFields obj2 = (PrimitiveFields) _serializer.Deserialize(obj1.GetType());

            if (!_compare.Compare(obj1, obj2))
                throw new Exception(_compare.DifferencesString);
        }

        /// <summary>
        /// This is a test to make sure the compare is working for the list
        /// </summary>
        [Test]
        public void PrimitiveFieldsListCompareTest()
        {
            List<PrimitiveFields> list1 = new List<PrimitiveFields>();

            PrimitiveFields obj1 = new PrimitiveFields();
            obj1.Setup();
            list1.Add(obj1);
            List<PrimitiveFields> list2 = Common.CloneWithSerialization(list1);

            if (!_compare.Compare(list1, list2))
                throw new Exception(_compare.DifferencesString);
        }

        /// <summary>
        /// Test serialization/deserialization of primitive types in a list
        /// </summary>
        [Test]
        public void PrimitiveFieldsListTest()
        {
            List<PrimitiveFields> list1 = new List<PrimitiveFields>();

            PrimitiveFields obj1 = new PrimitiveFields();
            obj1.Setup();
            list1.Add(obj1);
            
            _serializer.SerializeProperties = false;
            _serializer.Serialize(list1, list1.GetType());
            _memStream.Seek(0, SeekOrigin.Begin);
            List<PrimitiveFields> list2 =  (List<PrimitiveFields>) _serializer.Deserialize(list1.GetType());

            if (!_compare.Compare(list1, list2))
                throw new Exception(_compare.DifferencesString);
        }


        #endregion

        #region Primitive Fields Nullable Tests
        /// <summary>
        /// This is a test to make sure the compare is working
        /// </summary>
        [Test]
        public void PrimitiveFieldsNullableClassCompareTest()
        {
            PrimitiveFieldsNullable obj1 = new PrimitiveFieldsNullable();
            obj1.Setup();
            PrimitiveFieldsNullable obj2 = Common.CloneWithSerialization(obj1);

            if (!_compare.Compare(obj1, obj2))
                throw new Exception(_compare.DifferencesString);
        }

        /// <summary>
        /// Test serialization/deserialization of primitive types
        /// </summary>
        [Test]
        public void PrimitiveFieldsNullableClassTest()
        {
            PrimitiveFieldsNullable obj1 = new PrimitiveFieldsNullable();
            obj1.Setup();
            _serializer.SerializeProperties = false;
            _serializer.Serialize(obj1, obj1.GetType());
            _memStream.Seek(0, SeekOrigin.Begin);
            PrimitiveFieldsNullable obj2 = (PrimitiveFieldsNullable)_serializer.Deserialize(obj1.GetType());

            if (!_compare.Compare(obj1, obj2))
                throw new Exception(_compare.DifferencesString);
        }

        /// <summary>
        /// This is a test to make sure the compare is working for the list
        /// </summary>
        [Test]
        public void PrimitiveFieldsNullableListCompareTest()
        {
            List<PrimitiveFieldsNullable> list1 = new List<PrimitiveFieldsNullable>();

            PrimitiveFieldsNullable obj1 = new PrimitiveFieldsNullable();
            obj1.Setup();
            list1.Add(obj1);
            List<PrimitiveFieldsNullable> list2 = Common.CloneWithSerialization(list1);

            if (!_compare.Compare(list1, list2))
                throw new Exception(_compare.DifferencesString);
        }

        /// <summary>
        /// Test serialization/deserialization of primitive types in a list
        /// </summary>
        [Test]
        public void PrimitiveFieldsNullableListTest()
        {
            List<PrimitiveFieldsNullable> list1 = new List<PrimitiveFieldsNullable>();

            PrimitiveFieldsNullable obj1 = new PrimitiveFieldsNullable();
            obj1.Setup();
            list1.Add(obj1);

            _serializer.SerializeProperties = false;
            _serializer.Serialize(list1, list1.GetType());
            _memStream.Seek(0, SeekOrigin.Begin);
            List<PrimitiveFieldsNullable> list2 = (List<PrimitiveFieldsNullable>)_serializer.Deserialize(list1.GetType());

            if (!_compare.Compare(list1, list2))
                throw new Exception(_compare.DifferencesString);
        }
        #endregion

        #region Special Fields Tests
        /// <summary>
        /// This is a test to make sure the compare is working
        /// </summary>
        [Test]
        public void SpecialFieldsClassCompareTest()
        {
            SpecialFields obj1 = new SpecialFields();
            obj1.Setup();
            SpecialFields obj2 = Common.CloneWithSerialization(obj1);

            if (!_compare.Compare(obj1, obj2))
                throw new Exception(_compare.DifferencesString);
        }

        /// <summary>
        /// Test serialization/deserialization of primitive types
        /// </summary>
        [Test]
        public void SpecialFieldsClassTest()
        {
            SpecialFields obj1 = new SpecialFields();
            obj1.Setup();

            // This one doesn't work b/c there is no support (yet?) for mixed property and field serialization
            _serializer.SerializeProperties = false;
            _serializer.Serialize(obj1, obj1.GetType());
            _memStream.Seek(0, SeekOrigin.Begin);
            SpecialFields obj2 = (SpecialFields)_serializer.Deserialize(obj1.GetType());

            if (!_compare.Compare(obj1, obj2))
                throw new Exception(_compare.DifferencesString);
        }

        /// <summary>
        /// This is a test to make sure the compare is working for the list
        /// </summary>
        [Test]
        public void SpecialFieldsListCompareTest()
        {
            List<SpecialFields> list1 = new List<SpecialFields>();

            SpecialFields obj1 = new SpecialFields();
            obj1.Setup();
            list1.Add(obj1);
            List<SpecialFields> list2 = Common.CloneWithSerialization(list1);

            if (!_compare.Compare(list1, list2))
                throw new Exception(_compare.DifferencesString);
        }

        /// <summary>
        /// Test serialization/deserialization of primitive types in a list
        /// </summary>
        [Test]
        public void SpecialFieldsListTest()
        {
            List<SpecialFields> list1 = new List<SpecialFields>();

            SpecialFields obj1 = new SpecialFields();
            obj1.Setup();
            list1.Add(obj1);

            _serializer.SerializeProperties = false;
            _serializer.Serialize(list1, list1.GetType());
            _memStream.Seek(0, SeekOrigin.Begin);
            List<SpecialFields> list2 = (List<SpecialFields>)_serializer.Deserialize(list1.GetType());

            if (!_compare.Compare(list1, list2))
                throw new Exception(_compare.DifferencesString);
        }
        #endregion

        #region Primitive Property Tests
        /// <summary>
        /// This is a test to make sure the compare is working
        /// </summary>
        [Test]
        public void PrimitivePropertiesClassCompareTest()
        {
            PrimitiveProperties obj1 = new PrimitiveProperties();
            obj1.Setup();
            PrimitiveProperties obj2 = Common.CloneWithSerialization(obj1);

            if (!_compare.Compare(obj1, obj2))
                throw new Exception(_compare.DifferencesString);
        }

        /// <summary>
        /// Test serialization/deserialization of primitive types
        /// </summary>
        [Test]
        public void PrimitivePropertiesClassTest()
        {
            PrimitiveProperties obj1 = new PrimitiveProperties();
            obj1.Setup();

            _serializer.SerializeProperties = true;
            _serializer.Serialize(obj1, obj1.GetType());
            _memStream.Seek(0, SeekOrigin.Begin);
            PrimitiveProperties obj2 = (PrimitiveProperties)_serializer.Deserialize(obj1.GetType());

            if (!_compare.Compare(obj1, obj2))
                throw new Exception(_compare.DifferencesString);
        }

        /// <summary>
        /// This is a test to make sure the compare is working for the list
        /// </summary>
        [Test]
        public void PrimitivePropertiesListCompareTest()
        {
            List<PrimitiveProperties> list1 = new List<PrimitiveProperties>();

            PrimitiveProperties obj1 = new PrimitiveProperties();
            obj1.Setup();
            list1.Add(obj1);
            List<PrimitiveProperties> list2 = Common.CloneWithSerialization(list1);

            if (!_compare.Compare(list1, list2))
                throw new Exception(_compare.DifferencesString);
        }

        /// <summary>
        /// Test serialization/deserialization of primitive types in a list
        /// </summary>
        [Test]
        public void PrimitivePropertiesListTest()
        {
            List<PrimitiveProperties> list1 = new List<PrimitiveProperties>();

            PrimitiveProperties obj1 = new PrimitiveProperties();
            obj1.Setup();
            list1.Add(obj1);

            _serializer.SerializeProperties = true;
            _serializer.Serialize(list1, list1.GetType());
            _memStream.Seek(0, SeekOrigin.Begin);
            List<PrimitiveProperties> list2 = (List<PrimitiveProperties>)_serializer.Deserialize(list1.GetType());

            if (!_compare.Compare(list1, list2))
                throw new Exception(_compare.DifferencesString);
        }
        #endregion

        #region Primitive Property Nullable Tests
        /// <summary>
        /// This is a test to make sure the compare is working
        /// </summary>
        [Test]
        public void PrimitivePropertiesNullableClassCompareTest()
        {
            PrimitivePropertiesNullable obj1 = new PrimitivePropertiesNullable();
            obj1.Setup();
            PrimitivePropertiesNullable obj2 = Common.CloneWithSerialization(obj1);

            if (!_compare.Compare(obj1, obj2))
                throw new Exception(_compare.DifferencesString);
        }

        /// <summary>
        /// Test serialization/deserialization of primitive types
        /// </summary>
        [Test]
        public void PrimitivePropertiesNullableClassTest()
        {
            PrimitivePropertiesNullable obj1 = new PrimitivePropertiesNullable();
            obj1.Setup();
            _serializer.SerializeProperties = true;
            _serializer.Serialize(obj1, obj1.GetType());
            _memStream.Seek(0, SeekOrigin.Begin);
            PrimitivePropertiesNullable obj2 = (PrimitivePropertiesNullable)_serializer.Deserialize(obj1.GetType());

            if (!_compare.Compare(obj1, obj2))
                throw new Exception(_compare.DifferencesString);
        }

        /// <summary>
        /// This is a test to make sure the compare is working for the list
        /// </summary>
        [Test]
        public void PrimitivePropertiesNullableListCompareTest()
        {
            List<PrimitivePropertiesNullable> list1 = new List<PrimitivePropertiesNullable>();

            PrimitivePropertiesNullable obj1 = new PrimitivePropertiesNullable();
            obj1.Setup();
            list1.Add(obj1);
            List<PrimitivePropertiesNullable> list2 = Common.CloneWithSerialization(list1);

            if (!_compare.Compare(list1, list2))
                throw new Exception(_compare.DifferencesString);
        }

        /// <summary>
        /// Test serialization/deserialization of primitive types in a list
        /// </summary>
        [Test]
        public void PrimitivePropertiesNullableListTest()
        {
            List<PrimitivePropertiesNullable> list1 = new List<PrimitivePropertiesNullable>();

            PrimitivePropertiesNullable obj1 = new PrimitivePropertiesNullable();
            obj1.Setup();
            list1.Add(obj1);

            _serializer.SerializeProperties = true;
            _serializer.Serialize(list1, list1.GetType());
            _memStream.Seek(0, SeekOrigin.Begin);
            List<PrimitivePropertiesNullable> list2 = (List<PrimitivePropertiesNullable>)_serializer.Deserialize(list1.GetType());

            if (!_compare.Compare(list1, list2))
                throw new Exception(_compare.DifferencesString);
        }
        #endregion

        #region Null Tests
        [Test]
        public void NullObject()
        {
            Person obj1 = null;

            _serializer.SerializeProperties = false;
            _serializer.Serialize(obj1, typeof(Person));
            _memStream.Seek(0, SeekOrigin.Begin);
            Person obj2 = (Person)_serializer.Deserialize(typeof(Person));

            if (!_compare.Compare(obj1, obj2))
                throw new Exception(_compare.DifferencesString);

        }

        [Test]
        public void ListOfNullObjects()
        {
            Person p1 = null;
            Person p2 = null;

            List<Person> list1 = new List<Person>();
            list1.Add(p1);
            list1.Add(p2);

            _serializer.SerializeProperties = false;
            _serializer.Serialize(list1, typeof(List<Person>));
            _memStream.Seek(0, SeekOrigin.Begin);
            List<Person> list2 = (List<Person>)_serializer.Deserialize(typeof(List<Person>));

            if (!_compare.Compare(list1, list2))
                throw new Exception(_compare.DifferencesString);
        }
        #endregion

        #region Dictionary Tests
        [Test]
        public void TestDictionary()
        {
            Person p1 = new Person();
            p1.DateCreated = DateTime.Now;
            p1.Name = "Owen";
            Person p2 = new Person();
            p2.Name = "Greg";
            p2.DateCreated = DateTime.Now.AddDays(-1);

            Dictionary<string, Person> dict1 = new Dictionary<string, Person>();
            dict1.Add("1001", p1);
            dict1.Add("1002", p2);

            _serializer.SerializeProperties = false;
            _serializer.Serialize(dict1, typeof(Dictionary<string, Person>));
            _memStream.Seek(0, SeekOrigin.Begin);
            Dictionary<string, Person> dict2 = (Dictionary<string, Person>)_serializer.Deserialize(typeof(Dictionary<string, Person>));

            if (!_compare.Compare(dict1, dict2))
                throw new Exception(_compare.DifferencesString);

        }
        #endregion

        #region Struct Tests
        [Test]
        public void TestStruct()
        {
            Size size1 = new Size();
            size1.Width = 800;
            size1.Height = 600;

            Size size2 = new Size();
            size2.Width = 1024;
            size2.Height = 768;

            List<Size> list1 = new List<Size>();
            list1.Add(size1);
            list1.Add(size2);

            _serializer.SerializeProperties = false;
            _serializer.Serialize(list1, typeof(List<Size>));
            _memStream.Seek(0, SeekOrigin.Begin);
            List<Size> list2 = (List<Size>)_serializer.Deserialize(typeof(List<Size>));

            if (!_compare.Compare(list1, list2))
                throw new Exception(_compare.DifferencesString);
        }
        #endregion

        #region Enumeration Tests
        [Test]
        public void TestEnumeration()
        {
            List<Deck> list1 = new List<Deck>();
            list1.Add(Deck.Engineering);
            list1.Add(Deck.SickBay);

            _serializer.SerializeProperties = false;
            _serializer.Serialize(list1, typeof(List<Deck>));
            _memStream.Seek(0, SeekOrigin.Begin);
            List<Deck> list2 = (List<Deck>)_serializer.Deserialize(typeof(List<Deck>));

            if (!_compare.Compare(list1, list2))
                throw new Exception(_compare.DifferencesString);
        }

        [Test]
        public void TestNullableEnumeration()
        {
            List<Deck?> list1 = new List<Deck?>();
            list1.Add(Deck.Engineering);
            list1.Add(null);

            _serializer.SerializeProperties = false;
            _serializer.Serialize(list1, typeof(List<Deck?>));
            _memStream.Seek(0, SeekOrigin.Begin);
            List<Deck?> list2 = (List<Deck?>)_serializer.Deserialize(typeof(List<Deck?>));

            if (!_compare.Compare(list1, list2))
                throw new Exception(_compare.DifferencesString);
        }
        #endregion

        #region Array Tests
        [Test]
        public void ArrayTest()
        {
            Person p1 = new Person();
            p1.DateCreated = DateTime.Now;
            p1.Name = "Greg";

            Person p2 = new Person();
            p2.Name = "Owen";
            p2.DateCreated = DateTime.Now.AddDays(1);

            Person[] array1 = new Person[2];
            
            array1[0] = p1;
            array1[1] = p2;

            _serializer.SerializeProperties = false;
            _serializer.Serialize(array1, typeof(Person[]));
            _memStream.Seek(0, SeekOrigin.Begin);
            Person[] array2 = (Person[])_serializer.Deserialize(typeof(Person[]));

            if (!_compare.Compare(array1, array2))
                throw new Exception(_compare.DifferencesString);
        }

        [Test]
        public void MultiDimensionalByteArrayTest()
        {
            byte[,] bytes1 = new byte[3, 2];

            bytes1[0, 0] = 5;
            bytes1[1, 0] = 10;
            bytes1[2, 0] = 15;
            bytes1[0, 1] = 20;
            bytes1[1, 1] = 25;
            bytes1[2, 1] = 30;

            _serializer.SerializeProperties = false;
            _serializer.Serialize(bytes1, typeof(byte[,]));
            _memStream.Seek(0, SeekOrigin.Begin);
            byte[,] bytes2 = (byte[,])_serializer.Deserialize(typeof(byte[,]));

            if (!_compare.Compare(bytes1, bytes2))
                throw new Exception(_compare.DifferencesString);
        }
        #endregion

        #region Entity Tree Tests
        [Test]
        public void TestEntityTree()
        {
            List<Entity> entityTree = new List<Entity>();

            //Brave Sir Robin Security Company
            Entity top1 = new Entity();
            top1.Description = "Brave Sir Robin Security Company";
            top1.Parent = null;
            top1.EntityLevel = Level.Company;
            entityTree.Add(top1);

            Entity div1 = new Entity();
            div1.Description = "Minstrils";
            div1.EntityLevel = Level.Division;
            div1.Parent = top1;
            top1.Children.Add(div1);

            Entity div2 = new Entity();
            div2.Description = "Sub Contracted Fighting";
            div2.EntityLevel = Level.Division;
            div2.Parent = top1;
            top1.Children.Add(div2);

            Entity dep2 = new Entity();
            dep2.Description = "Trojan Rabbit Department";
            dep2.EntityLevel = Level.Department;
            dep2.Parent = div2;
            div2.Children.Add(dep2);

            //Roger the Shrubber's Fine Shrubberies
            Entity top1b = new Entity();
            top1b.Description = "Roger the Shrubber's Fine Shrubberies";
            top1b.Parent = null;
            top1b.EntityLevel = Level.Company;
            entityTree.Add(top1b);

            Entity div1b = new Entity();
            div1b.Description = "Manufacturing";
            div1b.EntityLevel = Level.Division;
            div1b.Parent = top1;
            top1b.Children.Add(div1b); // OWEN: bug in unit test? was (div1)... causing bad tree / endless loop (grandparent is also child...etc)

            Entity dep1b = new Entity();
            dep1b.Description = "Design Department";
            dep1b.EntityLevel = Level.Department;
            dep1b.Parent = div1b;
            div1b.Children.Add(dep1b);

            Entity dep2b = new Entity();
            dep2b.Description = "Arranging Department";
            dep2b.EntityLevel = Level.Department;
            dep2b.Parent = div1b;
            div1b.Children.Add(dep2b);

            Entity div2b = new Entity();
            div2b.Description = "Sales";
            div2b.EntityLevel = Level.Division;
            div2b.Parent = top1;
            top1b.Children.Add(div2b);

            _serializer.SerializeProperties = true;
            _serializer.CacheEnabled = true;
            _serializer.Serialize(entityTree, typeof(List<Entity>));
            _memStream.Seek(0, SeekOrigin.Begin);
            List<Entity> entityTreeCopy = (List<Entity>)_serializer.Deserialize(typeof(List<Entity>));

            if (!_compare.Compare(entityTree, entityTreeCopy))
                throw new Exception(_compare.DifferencesString);
        }
        #endregion

    }
}
